package it.gtd.swimpool.model.business;

import com.google.common.annotations.VisibleForTesting;
import it.gtd.swimpool.model.entity.User;
import it.gtd.swimpool.model.utils.RandomString;

import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

@Stateless
@LocalBean
public class AccountManager {
    private static final String EMAIL_PASS_RESET_SUBJECT = "Your password has been reset!";
    private static final String EMAIL_PASS_RESET_BODY = "Your new password is %s";

    @PersistenceContext
    private EntityManager entityManager;

    @EJB
    private CommunicationManager communicationManager;

    private RandomString randomString = new RandomString(10);

    public AccountManager() {
    }

    @VisibleForTesting
    AccountManager(EntityManager entityManager, CommunicationManager communicationManager) {
        this();

        checkNotNull(entityManager, "entityManager can't be null");
        checkNotNull(communicationManager, "communicationManager can't be null");

        this.entityManager = entityManager;
        this.communicationManager = communicationManager;
    }

    public void resetPassword(String email) {
        checkNotNull(email, "email can't be null");

        TypedQuery<User> selectUserByEmail = entityManager.createNamedQuery("User.byEmail", User.class);
        selectUserByEmail.setParameter("email", email);

        User user = selectUserByEmail.getSingleResult();
        this.resetPassword(user);
    }

    public void resetAccount(String username) {
        checkNotNull(username, "username can't be null");

        TypedQuery<User> selectUserByName = entityManager.createNamedQuery("User.byName", User.class);
        selectUserByName.setParameter("name", username);

        User user = selectUserByName.getSingleResult();
        this.resetPassword(user);
    }

    private void resetPassword(User user) {
        checkNotNull(user, "user can't be null");
        checkArgument(entityManager.contains(user), "User not contained in the EM");

        String newPassword = randomString.nextString();
        user.setPassword(newPassword);
        communicationManager.sendEmail(user, EMAIL_PASS_RESET_SUBJECT, String.format(EMAIL_PASS_RESET_BODY, newPassword));
    }
}
